package edu.washington.cs.workflow.instrument;

import java.util.Set;

import com.ibm.wala.shrikeBT.InvokeInstruction;
import com.ibm.wala.shrikeBT.MethodData;

import edu.washington.cs.workflow.analysis.SwingHelper;
import edu.washington.cs.workflow.util.Utils;

public class InstruPointsController {
	
	public final String[] appPackages;
	
	public InstruPointsController() {
		this(null);
	}
	
	public InstruPointsController(String[] appPackages) {
		this.appPackages = appPackages;
	}

	//XXX need revise
	public boolean isEventHandlingMethod(MethodData meData) {
		String methodName = meData.getName();
		Set<String> swingMethodNames = SwingHelper.getHandlerNames();
		return swingMethodNames.contains(methodName);
	}
	
	public boolean isInitMethod(MethodData meData) {
		String name = meData.getName();
		return name.equals("<init>") || name.equals("<clinit>");
	}
	
	public boolean isStaticMethod(MethodData meData) {
		return meData.getIsStatic();
	}
	
	public boolean isMethodSkippable(MethodData meData) {
		String classType = meData.getClassType().trim();
		String methodName = meData.getName();
		Utils.checkTrue(classType.startsWith("L") && classType.endsWith(";"));
		String classTypeName = Utils.translateSlashToDot(classType.substring(1, classType.length() - 1));


		String fullMethodName = classTypeName + "." + methodName;
		if(fullMethodName.equals("crosswordsage.MainScreen.jbInit")
			|| fullMethodName.equals("crosswordsage.MainScreen.<init>")
			|| fullMethodName.equals("crosswordsage.MainScreen.main")
			|| fullMethodName.equals("org.gjt.sp.util.Log$1")
			|| fullMethodName.equals("org.gjt.sp.jedit.textarea.JEditTextArea$CaretBlinker.actionPerformed")
			|| fullMethodName.equals("org.gjt.sp.jedit.Autosave.actionPerformed")
			|| fullMethodName.equals("org.gjt.sp.jedit.textarea.JEditTextArea$FocusHandler.focusLost")
			|| fullMethodName.equals("org.gjt.sp.jedit.View$FocusHandler.focusGained")
			|| fullMethodName.equals("org.gjt.sp.jedit.textarea.JEditTextArea$FocusHandler.focusGained")
			|| fullMethodName.equals("org.gjt.sp.jedit.textarea.JEditTextArea$ComponentHandler.componentResized")
			|| fullMethodName.equals("org.gjt.sp.jedit.View$WindowHandler.windowActivated")
			|| fullMethodName.equals("org.gjt.sp.jedit.textarea.JEditTextArea$AdjustHandler.adjustmentValueChanged")
			|| fullMethodName.equals("org.gjt.sp.jedit.gui.BufferTabs$ChangeHandler.stateChanged")
			|| fullMethodName.equals("org.gjt.sp.jedit.textarea.Gutter$GutterMouseListener.mouseExited")
			|| fullMethodName.equals("org.gjt.sp.jedit.View$WindowHandler.windowClosing")
			|| fullMethodName.startsWith("net.sf.jabref.util.")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.task.TaskContainmentHierarchyFacade")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.calendar.GPCalendar")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.task.Task")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.gui.NotificationManager")
			|| fullMethodName.startsWith("org.ganttproject")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.language") //FIXME
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.task")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.gui")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.undo")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.roles")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.resource")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.print")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.plugins")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.parser")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.io")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.importer")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.font")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.filter")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.export")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.document")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.application")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.search")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.client")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.action")
//			|| fullMethodName.startsWith("net.sourceforge.ganttproject.delay")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.util")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.time")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.shape")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.chart")
			|| fullMethodName.startsWith("net.sourceforge.ganttproject.calendar")
			) { //FIXME
			return true;
		}
		return false;
	}
	
	public boolean isSyntheticMethodByHeuristic(MethodData meData) {
		String methodName = meData.getName();
		return methodName.startsWith("access$");
	}
	
	public boolean isAppMethodToInstrument(MethodData meData) {
		String classType = meData.getClassType().trim();
		Utils.checkTrue(classType.startsWith("L") && classType.endsWith(";"));
		String classTypeName = Utils.translateSlashToDot(classType.substring(1, classType.length() - 1));
		
		String methodName = meData.getName();
		String fullMethodName = classTypeName + "." + methodName;
//		if(classTypeName.equals("crosswordsage.Preferences")) {
//			return false;
//		}
		
//		if(fullMethodName.equals("crosswordsage.Preferences.setProxyPort")) {
//			return true;
//		}
//				
		if(fullMethodName.equals("crosswordsage.Preferences.<init>")
			|| fullMethodName.equals("crosswordsage.Preferences.getCheckNewVersions")
			|| fullMethodName.equals("crosswordsage.Preferences.setCheckNewVersions")
			|| fullMethodName.equals("crosswordsage.Preferences.setUseProxy")
			|| fullMethodName.equals("crosswordsage.Preferences.getUseProxy")
			|| fullMethodName.equals("crosswordsage.Preferences.setProxy")
			|| fullMethodName.equals("crosswordsage.Preferences.getProxy")
			|| fullMethodName.equals("crosswordsage.Preferences.setProxyPort")
			|| fullMethodName.equals("crosswordsage.Preferences.getProxyPort")
			|| fullMethodName.equals("crosswordsage.Preferences.getProxyUserName")
			|| fullMethodName.equals("crosswordsage.Preferences.setProxyUserName")
			|| fullMethodName.equals("crosswordsage.Preferences.getProxyPassword")
			|| fullMethodName.equals("crosswordsage.Preferences.setProxyPassword")
				) {
			return false;
		}
		
		if(appPackages == null) {
			return true; //instrument everything
		} else {
			return Utils.startWith(classTypeName, appPackages);
		}
	}
	
	public boolean isGUIValueReturningMethod(InvokeInstruction instruction) {
		String clazzName = instruction.getClassType();
		String methodName = instruction.getMethodName();
		if(methodName.equals("getText")) {
			Utils.debugPrintln("find: " + clazzName  + "   --  " + methodName);
		    return true;
		}
		return false;
	}
	
}